package routine

import (
	"os"
	"os/signal"
	"sync/atomic"
	"syscall"
	"time"
)

const (
	//StatusStop 停止
	StatusStop = 0
	//StatusRunning 运行中
	StatusRunning = 1
)

var isRunning int32 //是否在运行
var exitChan = make(chan byte)

// 收尾需要准备的工作
var funcArrayAfterStop []func()

// PushFrontFuncAfterStop 执行退出时需要执行的工作排在第一个
func PushFrontFuncAfterStop(f func()) {
	if f == nil {
		return
	}
	fs := make([]func(), len(funcArrayAfterStop)+1)
	fs[0] = f
	copy(fs[1:], funcArrayAfterStop)
	funcArrayAfterStop = fs
}

// AddFuncAfterStop 执行退出时需要执行的工作
func AddFuncAfterStop(f func()) {
	if f == nil {
		return
	}
	funcArrayAfterStop = append(funcArrayAfterStop, f)
}

// WaitExit 等待退出
func WaitExit() {
	<-exitChan
	ExitMsg("All service is stopped.")
	os.Exit(0) //保证一定能退出
}

// Wait ...
// func Wait() <-chan byte {
// 	return exitChan
// }

func signalListen() {
	sign := make(chan os.Signal, 5)
	signal.Notify(sign, os.Interrupt, syscall.SIGTERM)
	<-sign
	ExitMsg("Received kill signal")
	Stop()
}

// Start 启动
func Start() {
	atomic.StoreInt32(&isRunning, StatusRunning)
	go signalListen()
}

// Stop 停止
func Stop() {
	if isRunning == StatusStop {
		return
	}
	atomic.StoreInt32(&isRunning, StatusStop)

	go Timeout()

	ExitMsg("Stopping all service")

	for _, f := range funcArrayAfterStop {
		f()
	}
	close(exitChan)
}

// Timeout 超时
func Timeout() {
	<-time.After(time.Second * 60)
	ExitMsg("Exit timeout")
	os.Exit(2)
}

// IsRunning 是否在运行
func IsRunning() bool {
	return (isRunning != StatusStop)
}

// Sleep 睡眠
func Sleep(ms int) {
	for ms > 0 && IsRunning() {
		if ms > 1000 {
			time.Sleep(time.Second)
			ms -= 1000
		} else {
			time.Sleep(time.Millisecond * time.Duration(ms))
			break
		}
	}
}

// ExitMsg 退出原因
func ExitMsg(msg string) {
	f, err := os.OpenFile("exit.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
	if err != nil {
		return
	}
	defer f.Close()
	f.WriteString(time.Now().Format("2006-01-02 15:04:05.999 ") + msg + "\r\n")
	f.Sync()
}
